import logging
import os
import sys
from datetime import datetime
from typing import Optional
import json
from config.settings import config


class EmoBotLogger:
    def __init__(self, name: str = "emobot", log_level: str = None):
        self.name = name
        # Use config.LOG_LEVEL if available, otherwise use parameter or default to INFO
        if log_level is None:
            log_level = getattr(config, "LOG_LEVEL", "INFO")
        self.log_level = getattr(logging, log_level.upper(), logging.INFO)

        # Create logs directory if it doesn't exist
        self.log_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "logs")
        os.makedirs(self.log_dir, exist_ok=True)

        # Create logger
        self.logger = logging.getLogger(name)
        self.logger.setLevel(self.log_level)

        # Configure root logger to ensure all messages are captured
        root_logger = logging.getLogger()
        root_logger.setLevel(
            logging.DEBUG
        )  # Set root logger to DEBUG to capture all messages

        # Clear existing handlers
        self.logger.handlers.clear()
        root_logger.handlers.clear()  # Clear root logger handlers to avoid duplicates

        # Create formatters
        self.console_formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        )

        self.file_formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s"
        )

        # Add console handler - always show DEBUG and INFO level messages in console
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(logging.DEBUG)  # Always show DEBUG level in console
        console_handler.setFormatter(self.console_formatter)
        self.logger.addHandler(console_handler)
        root_logger.addHandler(console_handler)  # Add to root logger too

        # Add file handler for general logs
        general_log_file = os.path.join(self.log_dir, f"{name}.log")
        file_handler = logging.FileHandler(general_log_file, encoding="utf-8")
        file_handler.setLevel(self.log_level)
        file_handler.setFormatter(self.file_formatter)
        self.logger.addHandler(file_handler)

        # Add error file handler
        error_log_file = os.path.join(self.log_dir, f"{name}_errors.log")
        error_handler = logging.FileHandler(error_log_file, encoding="utf-8")
        error_handler.setLevel(logging.ERROR)
        error_handler.setFormatter(self.file_formatter)
        self.logger.addHandler(error_handler)

        # Add API request handler
        api_log_file = os.path.join(self.log_dir, f"{name}_api.log")
        api_handler = logging.FileHandler(api_log_file, encoding="utf-8")
        api_handler.setLevel(logging.INFO)
        api_handler.setFormatter(self.file_formatter)
        self.api_logger = logging.getLogger(f"{name}_api")
        self.api_logger.setLevel(logging.INFO)
        self.api_logger.addHandler(api_handler)

        # Add database operation handler
        db_log_file = os.path.join(self.log_dir, f"{name}_db.log")
        db_handler = logging.FileHandler(db_log_file, encoding="utf-8")
        db_handler.setLevel(logging.INFO)
        db_handler.setFormatter(self.file_formatter)
        self.db_logger = logging.getLogger(f"{name}_db")
        self.db_logger.setLevel(logging.INFO)
        self.db_logger.addHandler(db_handler)

        # Add face recognition handler
        face_log_file = os.path.join(self.log_dir, f"{name}_face.log")
        face_handler = logging.FileHandler(face_log_file, encoding="utf-8")
        face_handler.setLevel(logging.INFO)
        face_handler.setFormatter(self.file_formatter)
        self.face_logger = logging.getLogger(f"{name}_face")
        self.face_logger.setLevel(logging.INFO)
        self.face_logger.addHandler(face_handler)

    def get_logger(self):
        return self.logger

    def log_api_request(
        self,
        method: str,
        endpoint: str,
        data: Optional[dict] = None,
        user_id: Optional[str] = None,
        session_id: Optional[str] = None,
    ):
        """Log API requests"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "method": method,
            "endpoint": endpoint,
            "user_id": user_id,
            "session_id": session_id,
            "data": data or {},
        }
        self.api_logger.info(f"API_REQUEST: {json.dumps(log_data, ensure_ascii=False)}")

    def log_api_response(
        self,
        method: str,
        endpoint: str,
        status_code: int,
        response_data: Optional[dict] = None,
        duration: Optional[float] = None,
    ):
        """Log API responses"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "method": method,
            "endpoint": endpoint,
            "status_code": status_code,
            "duration_ms": duration,
            "response_data": response_data or {},
        }
        self.api_logger.info(
            f"API_RESPONSE: {json.dumps(log_data, ensure_ascii=False)}"
        )

    def log_db_operation(
        self,
        operation: str,
        table: str,
        data: Optional[dict] = None,
        duration: Optional[float] = None,
        error: Optional[str] = None,
    ):
        """Log database operations"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "operation": operation,
            "table": table,
            "data": data or {},
            "duration_ms": duration,
            "error": error,
        }
        if error:
            self.db_logger.error(
                f"DB_ERROR: {json.dumps(log_data, ensure_ascii=False)}"
            )
        else:
            self.db_logger.info(
                f"DB_OPERATION: {json.dumps(log_data, ensure_ascii=False)}"
            )

    def log_face_operation(
        self,
        operation: str,
        user_id: Optional[str] = None,
        confidence: Optional[float] = None,
        error: Optional[str] = None,
    ):
        """Log face recognition operations"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "operation": operation,
            "user_id": user_id,
            "confidence": confidence,
            "error": error,
        }
        if error:
            self.face_logger.error(
                f"FACE_ERROR: {json.dumps(log_data, ensure_ascii=False)}"
            )
        else:
            self.face_logger.info(
                f"FACE_OPERATION: {json.dumps(log_data, ensure_ascii=False)}"
            )

    def log_conversation_event(
        self,
        event_type: str,
        user_id: str,
        session_id: str,
        message: Optional[str] = None,
        metadata: Optional[dict] = None,
    ):
        """Log conversation events"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": event_type,
            "user_id": user_id,
            "session_id": session_id,
            "message": message,
            "metadata": metadata or {},
        }
        self.logger.info(
            f"CONVERSATION_EVENT: {json.dumps(log_data, ensure_ascii=False)}"
        )


# Global logger instance
emobot_logger = EmoBotLogger()


def get_logger(name: str = "emobot") -> logging.Logger:
    """Get a logger instance"""
    return EmoBotLogger(name).get_logger()


def log_function_call(func_name: str, args: dict = None, kwargs: dict = None):
    """Log function call details"""
    logger = emobot_logger.get_logger()
    log_data = {"function": func_name, "args": args or {}, "kwargs": kwargs or {}}
    logger.debug(f"FUNCTION_CALL: {json.dumps(log_data, ensure_ascii=False)}")


def log_function_result(func_name: str, result: any, duration: float = None):
    """Log function result"""
    logger = emobot_logger.get_logger()
    log_data = {
        "function": func_name,
        "duration_ms": duration,
        "result_type": type(result).__name__,
    }
    logger.debug(f"FUNCTION_RESULT: {json.dumps(log_data, ensure_ascii=False)}")


def log_function_error(
    func_name: str, error: Exception, args: dict = None, kwargs: dict = None
):
    """Log function error"""
    logger = emobot_logger.get_logger()
    log_data = {
        "function": func_name,
        "error_type": type(error).__name__,
        "error_message": str(error),
        "args": args or {},
        "kwargs": kwargs or {},
    }
    logger.error(f"FUNCTION_ERROR: {json.dumps(log_data, ensure_ascii=False)}")
